package com.meiyuetao.myt.sale.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.pagination.GroupPropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter.MatchType;
import lab.s2jh.core.security.AuthContextHolder;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.ctx.DynamicConfigService;
import lab.s2jh.ctx.FreemarkerService;
import lab.s2jh.ctx.MailService;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.meiyuetao.myt.customer.dao.CustomerAccountHistDao;
import com.meiyuetao.myt.customer.dao.CustomerProfileDao;
import com.meiyuetao.myt.customer.entity.CustomerProfile;
import com.meiyuetao.myt.customer.service.CustomerAccountHistService;
import com.meiyuetao.myt.job.BusinessNotifyService;
import com.meiyuetao.myt.md.entity.Commodity.CommodityTypeEnum;
import com.meiyuetao.myt.md.entity.Commodity.PurchaseCodeExpireRuleEnum;
import com.meiyuetao.myt.partner.dao.PurchaseCodeDao;
import com.meiyuetao.myt.partner.entity.PurchaseCode;
import com.meiyuetao.myt.partner.entity.PurchaseCode.PurchaseCodeStatusEnum;
import com.meiyuetao.myt.sale.dao.BoxOrderDao;
import com.meiyuetao.myt.sale.dao.BoxOrderDetailDao;
import com.meiyuetao.myt.sale.dao.BoxOrderInDeLogDao;
import com.meiyuetao.myt.sale.dao.OrderTracingDao;
import com.meiyuetao.myt.sale.entity.BoxOrder;
import com.meiyuetao.myt.sale.entity.BoxOrder.BoxOrderStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail.BoxOrderDetailStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail.CommoditiesTypeEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetailCommodity;
import com.meiyuetao.myt.sale.entity.BoxOrderInDeLog;
import com.meiyuetao.myt.sale.entity.OrderTracing;

@Service
@Transactional
public class BoxOrderDetailService extends BaseService<BoxOrderDetail, Long> {

    @Autowired
    private BoxOrderDetailDao boxOrderDetailDao;
    @Autowired
    private BoxOrderDao boxOrderDao;
    @Autowired
    private CustomerAccountHistDao customerAccountHistDao;
    @Autowired
    private BoxOrderInDeLogDao boxOrderInDeLogDao;
    @Autowired
    private MailService mailService;
    @Autowired
    private CustomerProfileDao customerProfileDao;
    @Autowired
    private BusinessNotifyService businessNotifyService;
    @Autowired
    private PurchaseCodeDao purchaseCodeDao;
    @Autowired
    private DynamicConfigService dynamicConfigService;
    @Autowired
    private CustomerAccountHistService customerAccountHistService;
    @Autowired
    private OrderTracingDao orderTracingDao;
    @Autowired
    private FreemarkerService freemarkerService;
    @Autowired
    private BoxOrderDetailCommodityService boxOrderDetailCommodityService;

    @Override
    protected BaseDao<BoxOrderDetail, Long> getEntityDao() {
        return boxOrderDetailDao;
    }

    public void genPurchaseCode(BoxOrderDetail boxOrderDetail) {
        List<PurchaseCode> purchaseCodes = new ArrayList<PurchaseCode>();
        BoxOrder boxOrder = boxOrderDetail.getBoxOrder();
        List<BoxOrderDetailCommodity> boxOrderDetailCommoditys = boxOrderDetail.getBoxOrderDetailCommodities();
        for (BoxOrderDetailCommodity boxOrderDetailCommodity : boxOrderDetailCommoditys) {
            if (boxOrderDetailCommodity.getCommodity().getPurchaseCodeExpireRule() != null
                    && CommodityTypeEnum.SERVICE.equals(boxOrderDetailCommodity.getCommodity().getCommodityType())) {
                String code = RandomStringUtils.randomNumeric(8);
                while (purchaseCodeDao.findByCode(code) != null) {
                    code = RandomStringUtils.randomNumeric(8);
                }
                PurchaseCode purchaseCode = new PurchaseCode();
                purchaseCode.setCode(code);
                purchaseCode.setBoxOrder(boxOrder);
                purchaseCode.setBoxOrderDetailCommodity(boxOrderDetailCommodity);
                purchaseCode.setCommodity(boxOrderDetailCommodity.getCommodity());
                purchaseCode.setCodeStatus(PurchaseCodeStatusEnum.ENABLE);
                purchaseCode.setGenDatetime(new Date());
                if (PurchaseCodeExpireRuleEnum.FIXED.equals(boxOrderDetailCommodity.getCommodity().getPurchaseCodeExpireRule())) {
                    purchaseCode.setExpiredDatetime(boxOrderDetailCommodity.getCommodity().getPurchaseCodeExpiredDatetime());
                }
                if (PurchaseCodeExpireRuleEnum.POSTPONE.equals(boxOrderDetailCommodity.getCommodity().getPurchaseCodeExpireRule())) {
                    Calendar expiredDatetimeCalendar = Calendar.getInstance();
                    expiredDatetimeCalendar.setTime(new Date());
                    expiredDatetimeCalendar.add(Calendar.DAY_OF_YEAR, boxOrderDetailCommodity.getCommodity().getPurchaseCodeExpiredDays() + 1);
                    expiredDatetimeCalendar.add(Calendar.SECOND, -1);
                    purchaseCode.setExpiredDatetime(expiredDatetimeCalendar.getTime());
                }
                if (boxOrderDetailCommodity.getCommodity().getPartner() != null) {
                    purchaseCode.setPartner(boxOrderDetailCommodity.getCommodity().getPartner());

                }
                purchaseCodeDao.save(purchaseCode);
                purchaseCodes.add(purchaseCode);

            }
        }

        // 消费码通知短信
        for (PurchaseCode purchaseCode : purchaseCodes) {
            Map<String, Object> dataMapSMS = new HashMap<String, Object>();
            dataMapSMS.put("purchaseCode", purchaseCode);
            String smsHTML = freemarkerService.processTemplateByFileName("ORDER_PURCHASECODE_NOTIFY_SMS", dataMapSMS);

            if (StringUtils.isNotBlank(smsHTML) && StringUtils.isNotBlank(boxOrder.getMobilePhone())) {
                businessNotifyService.sendMsg(boxOrder.getMobilePhone(), smsHTML);
                ;
            }
        }

        // Service商品发货
        if (boxOrderDetail.getCommoditiesType() != null && !CommoditiesTypeEnum.GOODS.equals(boxOrderDetail.getCommoditiesType())) {
            if (CommoditiesTypeEnum.SERVICE.equals(boxOrderDetail.getCommoditiesType())) {
                boxOrderDetail.setOrderDetailStatus(BoxOrderDetailStatusEnum.S50DF);
                boxOrderDetailDao.save(boxOrderDetail);
            }
            if (CommoditiesTypeEnum.COMBINE.equals(boxOrderDetail.getCommoditiesType())) {
                GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
                groupPropertyFilter.append(new PropertyFilter(MatchType.FETCH, "commodity", "INNER"));
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "boxOrderDetail", boxOrderDetail));
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "commodity.commodityType", CommodityTypeEnum.SERVICE));
                List<BoxOrderDetailCommodity> boxOrderDetailCommodities = boxOrderDetailCommodityService.findByFilters(groupPropertyFilter);
                boxOrderDetail.setDeliveriedQuantity(boxOrderDetailCommodities.size());
                boxOrderDetail.setOrderDetailStatus(BoxOrderDetailStatusEnum.S40DP);
                boxOrderDetailDao.save(boxOrderDetail);
            }
        }
        List<BoxOrderDetail> boxOrderDetails = boxOrder.getBoxOrderDetails();
        BoxOrderStatusEnum orderStatus = BoxOrderStatusEnum.S50DF;
        for (BoxOrderDetail item : boxOrderDetails) {
            if (BoxOrderDetailStatusEnum.S40DP.equals(item.getOrderDetailStatus())) {
                orderStatus = BoxOrderStatusEnum.S40DP;
            }
        }
        boxOrder.setOrderStatus(orderStatus);
        boxOrderDao.save(boxOrder);

    }

    public BoxOrderDetail modifyPrice(BoxOrderDetail entity) {
        BoxOrderDetail dbEntity = boxOrderDetailDao.findOne(entity.getId());
        if (!entity.getActualAmount().equals(dbEntity.getActualAmount())) {
            entity.setPrice(entity.getActualAmount());
            BoxOrder boxOrder = entity.getBoxOrder();
            BigDecimal diff = entity.getActualAmount().subtract(dbEntity.getActualAmount());
            if (entity.getOrderDetailStatus().equals(BoxOrderDetailStatusEnum.S10O) || entity.getOrderDetailStatus().equals(BoxOrderDetailStatusEnum.S15O)) {
                BigDecimal detailActualAmount = entity.getActualAmount();
                BigDecimal detailOriginalAmount = entity.getOriginalAmount();
                BigDecimal perActualAmount = detailActualAmount.divide(detailOriginalAmount, 5, BigDecimal.ROUND_HALF_EVEN);
                BigDecimal tempActualAmount = BigDecimal.ZERO;
                BigDecimal iActualAmount = BigDecimal.ZERO;
                List<BoxOrderDetailCommodity> boxOrderDetailCommodities = entity.getBoxOrderDetailCommodities();
                for (int i = 0; i < boxOrderDetailCommodities.size(); i++) {
                    BoxOrderDetailCommodity bodc = boxOrderDetailCommodities.get(i);
                    if (i != boxOrderDetailCommodities.size() - 1) {
                        iActualAmount = perActualAmount.multiply(bodc.getOriginalAmount());
                        tempActualAmount = tempActualAmount.add(iActualAmount);
                    } else {
                        iActualAmount = detailActualAmount.subtract(tempActualAmount);
                    }
                    bodc.setActualAmount(iActualAmount);
                    bodc.setDiscountAmount(bodc.getOriginalAmount().subtract(iActualAmount));
                }

                boxOrder.setActualAmount(boxOrder.getActualAmount().add(diff));
                boxOrder.setDiscountAmount(boxOrder.getDiscountAmount().subtract(diff));
                boxOrderDao.save(boxOrder);

                // TODO: 写入订单条件记录数据
                BoxOrderInDeLog boid = new BoxOrderInDeLog();
                boid.setBoxOrder(boxOrder);
                boid.setBoxOrderDetail(entity);
                boid.setInDeAmount(diff);
                boid.setReason("行项调价--数量：" + entity.getQuantity() + ",初始金额：" + entity.getOriginalAmount() + ",小计价:" + entity.getActualAmount() + "  (原数量：" + dbEntity.getQuantity()
                        + ",原初始金额：" + dbEntity.getOriginalAmount() + ",原小计价：" + dbEntity.getActualAmount() + ")");
                boid.setOccurTime(new Date());
                boid.setMoneyOperator(AuthContextHolder.getAuthUserPin());
                boxOrderInDeLogDao.save(boid);
            } else {
                throw new RuntimeException("行项状态为“用户已下单”或“计划进行中”才允许行项改价");
            }
        }
        return super.save(entity);
    }

    // 确认收货
    public void recvConfirm(BoxOrderDetail entity) {
        // 计算订单预期完结时间
        String days = dynamicConfigService.getString("cfg.order.success.days", "30");
        Calendar successDate = Calendar.getInstance();
        successDate.add(Calendar.DAY_OF_MONTH, Integer.valueOf(days));
        entity.setOrderDetailStatus(BoxOrderDetailStatusEnum.S60R);
        entity.setActualConfirmTime(new Date());

        entity.setActualConfirmOperator(AuthContextHolder.getAuthUserPin());
        entity.setAutoSuccessTime(successDate.getTime());
        // 追加操作记录
        entity.addOperationEvent("订单行项确认收货", AuthContextHolder.getAuthUserPin());
        this.save(entity);
    }

    /*
     * public void successClose(BoxOrderDetail entity) {
     * 
     * //必须已付款确认 Validation.isTrue(entity.getPayTime() != null,
     * "行项无付款，不能完结，请取消"); //追加操作记录 entity.addOperationEvent("订单行项完结",
     * AuthContextHolder.getAuthUserPin()); //已处理过直接返回 if
     * (entity.getActualSuccessTime() != null) { return; }
     * 
     * Date now = new Date();
     * 
     * //更新当前订单已处理标志
     * entity.setOrderDetailStatus(BoxOrderDetailStatusEnum.S70CLS);
     * entity.setActualSuccessTime(now);
     * entity.setActualSuccessOperator(AuthContextHolder.getAuthUserPin());
     * this.save(entity);
     * 
     * CustomerProfile orderCustomerProfile = entity.getCustomerProfile();
     * CustomerProfile intermediaryCustomerProfile =
     * entity.getBoxOrder().getIntermediaryCustomerProfile(); //分期付款订单行项处理 if
     * (entity.getBoxOrder().getSplitPayMode() != null &&
     * !BoxOrderSplitPayModeEnum
     * .NO.equals(entity.getBoxOrder().getSplitPayMode())) { //订单推荐人提成 if
     * (intermediaryCustomerProfile != null) { //计算订单总计提成金额 BigDecimal
     * totalOrderReward = new BigDecimal(0); for (CustomerAccountHist
     * customerAccountHist : entity.getCustomerAccountHists()) { if
     * (CustomerAccountHistAccountTypeEnum
     * .FROZEN.equals(customerAccountHist.getAccountType())) { totalOrderReward
     * = totalOrderReward.add(customerAccountHist.getAmount()); } }
     * //追加当前账户金额并添加冲销入账记录 if (intermediaryCustomerProfile.getCurrentAccount()
     * == null) {
     * intermediaryCustomerProfile.setCurrentAccount(totalOrderReward); } else {
     * intermediaryCustomerProfile
     * .setCurrentAccount(intermediaryCustomerProfile.getCurrentAccount().add(
     * totalOrderReward)); } CustomerAccountHist customerAccountHist = new
     * CustomerAccountHist();
     * customerAccountHist.setCustomerProfile(intermediaryCustomerProfile);
     * customerAccountHist.setAmount(totalOrderReward.negate());
     * customerAccountHist.setOccurType(CustomerAccountHistOccurTypeEnum.DED);
     * customerAccountHist.setOccurTime(new Date());
     * customerAccountHist.setBoxOrder(entity.getBoxOrder());
     * customerAccountHist.setBoxOrderDetail(entity);
     * customerAccountHist.setAccountType
     * (CustomerAccountHistAccountTypeEnum.FROZEN);
     * customerAccountHist.setSysMemo("冲销订单" +
     * entity.getBoxOrder().getOrderSeq() + "的冻结提成金额");
     * customerAccountHistService.save(customerAccountHist);
     * 
     * //冲销冻结金额并添加入账记录
     * intermediaryCustomerProfile.setFrozenAccount(intermediaryCustomerProfile
     * .getFrozenAccount().subtract( totalOrderReward)); CustomerAccountHist
     * customerAccountHist2 = new CustomerAccountHist();
     * customerAccountHist2.setCustomerProfile(intermediaryCustomerProfile);
     * customerAccountHist2.setAmount(totalOrderReward);
     * customerAccountHist2.setOccurType(CustomerAccountHistOccurTypeEnum.DED);
     * customerAccountHist2.setOccurTime(new Date());
     * customerAccountHist2.setBoxOrder(entity.getBoxOrder());
     * customerAccountHist2.setBoxOrderDetail(entity);
     * customerAccountHist2.setAccountType
     * (CustomerAccountHistAccountTypeEnum.CURRENT);
     * customerAccountHist2.setSysMemo("订单" + entity.getBoxOrder().getOrderSeq()
     * + "的提成金额"); customerAccountHistService.save(customerAccountHist2);
     * 
     * customerProfileDao.save(intermediaryCustomerProfile); }
     * 
     * //冻结积分转有效积分处理 List<Score> scores = entity.getScores(); if
     * (CollectionUtils.isNotEmpty(scores)) { //计算冻结总结分 Integer totalScores = 0;
     * for (Score score : scores) { if (score.getScorePending() == null ||
     * score.getScorePending()) { score.setScorePending(false);
     * score.setEffectiveTime(now); totalScores += score.getScoreAmount(); } }
     * 
     * //追加当前积分 if (orderCustomerProfile.getScore() == null) {
     * orderCustomerProfile.setScore(totalScores); } else {
     * orderCustomerProfile.setScore(orderCustomerProfile.getScore() +
     * totalScores); }
     * 
     * //冲销冻结积分
     * orderCustomerProfile.setFrozenScore(orderCustomerProfile.getFrozenScore()
     * - totalScores);
     * 
     * customerProfileDao.save(orderCustomerProfile); }
     * 
     * //http://oa.rpset.net:3000/issues/2004
     * //更新用户值，主要用于用户的等级判断，正常情况下等同于spent_money if
     * (orderCustomerProfile.getCustomerValue() == null) {
     * orderCustomerProfile.setCustomerValue(entity.getPayAmount()); } else {
     * orderCustomerProfile
     * .setCustomerValue(orderCustomerProfile.getCustomerValue()
     * .add(entity.getPayAmount())); } } OrderTracing orderTracing = new
     * OrderTracing(); orderTracing.setBoxOrder(entity.getBoxOrder());
     * orderTracing.setOrderDetailSid(entity.getId());
     * orderTracing.setOccurTime(new Date());
     * orderTracing.setTracingText("您的当期订单已完成");
     * orderTracing.setCustomerProfile(orderCustomerProfile);
     * orderTracingDao.save(orderTracing); }
     */
    public void successClose(BoxOrderDetail entity) {
        // 追加操作记录
        entity.addOperationEvent("订单行项完结", AuthContextHolder.getAuthUserPin());
        // 已处理过直接返回
        if (entity.getActualSuccessTime() != null) {
            return;
        }

        Date now = new Date();
        // 更新当前订单行项已处理标志
        entity.setOrderDetailStatus(BoxOrderDetailStatusEnum.S70CLS);
        entity.setActualSuccessTime(now);
        entity.setActualSuccessOperator(AuthContextHolder.getAuthUserPin());
        this.save(entity);

        CustomerProfile orderCustomerProfile = entity.getCustomerProfile();
        OrderTracing orderTracing = new OrderTracing();
        orderTracing.setBoxOrder(entity.getBoxOrder());
        orderTracing.setOrderDetailSid(entity.getId());
        orderTracing.setOccurTime(new Date());
        orderTracing.setTracingText("您的当期订单已完成");
        orderTracing.setCustomerProfile(orderCustomerProfile);
        orderTracingDao.save(orderTracing);
    }

    public void deliverySave(BoxOrderDetail boxOrderDetail) {
        boxOrderDetail.setOrderDetailStatus(BoxOrderDetailStatusEnum.S50DF);
        boxOrderDetail.setDeliveryFinishTime(new Date());
        boxOrderDetailDao.save(boxOrderDetail);
        BoxOrder boxOrder = boxOrderDetail.getBoxOrder();
        Boolean isOrderDeliveryFinish = true;
        for (BoxOrderDetail bod : boxOrder.getBoxOrderDetails()) {
            if (!BoxOrderDetailStatusEnum.S50DF.equals(bod.getOrderDetailStatus())) {
                isOrderDeliveryFinish = false;
                break;
            }
        }
        if (isOrderDeliveryFinish) {
            boxOrder.setOrderStatus(BoxOrderStatusEnum.S50DF);
            boxOrder.setDeliveryFinishTime(new Date());
            boxOrderDao.save(boxOrder);
        }
        // 订单追踪表，发货的时候添加通知
        OrderTracing orderTracing = new OrderTracing();
        orderTracing.setBoxOrder(boxOrderDetail.getBoxOrder());
        orderTracing.setOrderDetailSid(boxOrderDetail.getId());
        orderTracing.setOccurTime(new Date());
        orderTracing.setTracingText("您的当期订单已发货");
        orderTracing.setCustomerProfile(boxOrderDetail.getCustomerProfile());
        orderTracingDao.save(orderTracing);
    }

    public BoxOrderDetail findByBoxOrderAndSn(BoxOrder boxOrder, String sn) {
        if (boxOrder.isNew()) {
            return new BoxOrderDetail();
        }
        return boxOrderDetailDao.findByBoxOrderAndSn(boxOrder, sn);
    }

}
